package me.zhengjie.modules.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import me.zhengjie.constant.ConstantUtils;
import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.service.IdentityAcctOperateManagerService;
import me.zhengjie.modules.system.service.dto.LoginUserIdentityRespDTO;
import me.zhengjie.modules.system.service.dto.PartnerListRespDTO;
import me.zhengjie.modules.system.service.dto.PartnerUserListRespDTO;
import me.zhengjie.modules.system.service.dto.WxUserDto;
import me.zhengjie.modules.system.service.dto.operate.*;
import me.zhengjie.modules.web.service.mybatisplus.*;
import me.zhengjie.utils.DateUtil;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class IdentityAcctOperateManagerServiceImpl implements IdentityAcctOperateManagerService {

    @Autowired
    private IWxUserPlusService wxUserPlusService;

    @Autowired
    private IDisOrderPlusService disOrderPlusService;

    @Autowired
    private IDisPartnerPlusService disPartnerPlusService;

    @Autowired
    private IDisPartnerUserPlusService disPartnerUserPlusService;

    @Autowired
    private IDisChannelPlusService disChannelPlusService;

    @Autowired
    private IDisChannelMemberPlusService memberPlusService;

    private static final Logger log = LoggerFactory.getLogger(IdentityAcctOperateManagerServiceImpl.class);

    @Override
    public SalesPerformanceRespDTO salesPerformance(SalesPerformanceReqDTO reqDTO) {
        SalesPerformanceRespDTO respDTO = new SalesPerformanceRespDTO();
        LambdaQueryWrapper<DisOrder> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(reqDTO.getOpenId())){
            wrapper.eq(DisOrder::getOpenId,reqDTO.getOpenId());
        }
        if (StringUtils.isNotBlank(reqDTO.getRealName())){
            wrapper.like(DisOrder::getRealName,reqDTO.getRealName());
        }
        if (StringUtils.isNotBlank(reqDTO.getStartTime()) && StringUtils.isNotBlank(reqDTO.getEndTime())){
            wrapper.between(DisOrder::getCreateTime,reqDTO.getStartTime(),reqDTO.getEndTime());
        }
        boolean queryPartnerFlag = false;
        if (Objects.nonNull(reqDTO.getPartnerId())){
            List<DisPartnerUser> partnerUserList = getPartnerUserList(reqDTO.getPartnerId());
            if (!CollectionUtils.isEmpty(partnerUserList)){
                List<String> collect = partnerUserList.stream().map(DisPartnerUser::getOpenId).collect(Collectors.toList());
                wrapper.in(DisOrder::getOpenId,collect);
                queryPartnerFlag = true;
            }
        }
        LoginUserIdentityRespDTO identityRespDTO = loginUserIdentity();
        if (!queryPartnerFlag && Objects.nonNull(identityRespDTO) &&
            Objects.nonNull(identityRespDTO.getPartnerId()) &&
            !identityRespDTO.getPartnerId().equals(reqDTO.getPartnerId()) &&
            identityRespDTO.getUserIdentity().equals(LoginUserIdentityRespDTO.UserIdentityEnum.Manager.getUserIdentity())){
            List<DisPartnerUser> partnerUserList = getPartnerUserList(identityRespDTO.getPartnerId());
            if (!CollectionUtils.isEmpty(partnerUserList)){
                List<String> collect = partnerUserList.stream().map(DisPartnerUser::getOpenId).collect(Collectors.toList());
                wrapper.in(DisOrder::getOpenId,collect);
            }
        }
        List<DisOrder> list = disOrderPlusService.list(wrapper);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        BigDecimal totalAmount = list.parallelStream().filter(Objects::nonNull).map(DisOrder::getCommission).reduce(BigDecimal.ZERO, BigDecimal::add);
        respDTO.setTotalAmount(totalAmount);

        Map<String, List<DisOrder>> monthMap = list.parallelStream().collect(Collectors.groupingBy(s -> DateUtil.date2String(DateUtil.timeStamp2Date(s.getCreateTime()), "yyyy-MM")));

        List<SalesPerformanceRespDTO.SalesDetail> salesDetails = new ArrayList<>();
        for (DisOrder disOrder : list) {
            SalesPerformanceRespDTO.SalesDetail detail = new SalesPerformanceRespDTO.SalesDetail();
            detail.setGoodsName(disOrder.getBizOrderTitle());
            detail.setCreateTime(DateUtil.getTimeStamp(disOrder.getCreateTime()));
            detail.setMobile(disOrder.getMobile());
            detail.setOrderAmount(disOrder.getOrderAmount());
            detail.setCommission(disOrder.getCommission());
            detail.setNickName(disOrder.getNickName());
            detail.setRealName(disOrder.getRealName());
            salesDetails.add(detail);
        }
        respDTO.setSalesDetailList(salesDetails);
        List<SalesPerformanceRespDTO.SalesPreformance> salesPreformances = new ArrayList<>();
        monthMap.forEach((k,v) -> {
            SalesPerformanceRespDTO.SalesPreformance salesPreformance = new SalesPerformanceRespDTO.SalesPreformance();
            salesPreformance.setMonth(k);
            BigDecimal salesAmount = v.parallelStream().filter(Objects::nonNull).map(DisOrder::getCommission).reduce(BigDecimal.ZERO, BigDecimal::add);
            salesPreformance.setSalesAmount(salesAmount);
            salesPreformances.add(salesPreformance);
        });
        respDTO.setPreformanceList(salesPreformances);
        return respDTO;
    }

    @Override
    public Page<OperateManagerRespDTO> operateManager(OperateManagerReqDTO reqDTO, Pageable pageable) {
        Page<WxUser> page = Page.of((pageable.getPageNumber()-1)*pageable.getPageSize(), pageable.getPageSize());

        LambdaQueryWrapper<WxUser> wxUserWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(reqDTO.getIdentityNo())){
            wxUserWrapper.eq(WxUser::getIdentityNo,reqDTO.getIdentityNo());
        }
        if (StringUtils.isNotBlank(reqDTO.getMobile())){
            wxUserWrapper.eq(WxUser::getMobile,reqDTO.getMobile());
        }
        if (StringUtils.isNotBlank(reqDTO.getNickName())){
            wxUserWrapper.like(WxUser::getNickname,reqDTO.getNickName());
        }
        if (StringUtils.isNotBlank(reqDTO.getRealName())){
            wxUserWrapper.like(WxUser::getRealName,reqDTO.getRealName());
        }
        boolean querySuperior = false;
        if (StringUtils.isNotBlank(reqDTO.getOpenId())){
            wxUserWrapper.eq(WxUser::getSuperior,reqDTO.getOpenId());
            querySuperior = true;
        }

        LoginUserIdentityRespDTO identityRespDTO = loginUserIdentity();
        if (Objects.nonNull(identityRespDTO) && Objects.nonNull(identityRespDTO.getPartnerId())){
            if (!querySuperior){
                List<DisPartnerUser> partnerUserList = getPartnerUserList(identityRespDTO.getPartnerId());
                if (!CollectionUtils.isEmpty(partnerUserList)){
                    List<String> collect = partnerUserList.stream().map(DisPartnerUser::getOpenId).collect(Collectors.toList());
                    wxUserWrapper.in(WxUser::getSuperior,collect);
                }
            }
        }else if (Objects.nonNull(identityRespDTO) &&
                identityRespDTO.getUserIdentity().equals(LoginUserIdentityRespDTO.UserIdentityEnum.Manager.getUserIdentity()) &&
                identityRespDTO.getUserIdentity().equals(LoginUserIdentityRespDTO.UserIdentityEnum.SubManager.getUserIdentity()))
        {
            //todo 无绑定关系查不了
        }

        Page<WxUser> wxUserPage = wxUserPlusService.page(page, wxUserWrapper);
        if (Objects.isNull(wxUserPage) || CollectionUtils.isEmpty(wxUserPage.getRecords())){
            return null;
        }

        Page<OperateManagerRespDTO> respDTOPage = new Page<>();
        respDTOPage.setTotal(wxUserPage.getTotal());
        respDTOPage.setSize(wxUserPage.getSize());
        respDTOPage.setCurrent(wxUserPage.getCurrent());
        respDTOPage.setPages(wxUserPage.getPages());
        respDTOPage.setMaxLimit(wxUserPage.maxLimit());
        List<OperateManagerRespDTO> respList = new ArrayList<>();

        List<WxUser> records = wxUserPage.getRecords();
        for (WxUser record : records) {
            OperateManagerRespDTO respDTO = new OperateManagerRespDTO();
            respDTO.setIdentityNo(record.getIdentityNo());
            respDTO.setIdentityName(record.getIdentityName());
            respDTO.setMobile(record.getMobile());
            respDTO.setRealName(record.getRealName());
            respDTO.setNickName(record.getNickname());
            respDTO.setSaleAmount(BigDecimal.ZERO);
            respDTO.setOpenId(record.getOpenId());
            LambdaQueryWrapper<DisOrder> orderWrapper = new LambdaQueryWrapper<>();
            orderWrapper.eq(DisOrder::getOpenId,record.getOpenId());
            List<DisOrder> list = disOrderPlusService.list(orderWrapper);
            if (!CollectionUtils.isEmpty(list)){
                BigDecimal totalAmount = list.parallelStream().filter(Objects::nonNull).map(DisOrder::getCommission).reduce(BigDecimal.ZERO, BigDecimal::add);
                respDTO.setSaleAmount(totalAmount);
            }
            respList.add(respDTO);
        }
        respDTOPage.setRecords(respList);
        return respDTOPage;
    }


    @Override
    public List<OperateManagerOrderListRespDTO> orderList(OperateManagerOrderListReqDTO reqDTO, Pageable pageable) {

        Page<DisOrder> page = Page.of((pageable.getPageNumber()-1)*pageable.getPageSize(), pageable.getPageSize());

        LambdaQueryWrapper<DisOrder> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(DisOrder::getOpenId,reqDTO.getOpenId());
        Page<DisOrder> pageDisOrder = disOrderPlusService.page(page,orderWrapper);
        if (Objects.isNull(pageDisOrder) || CollectionUtils.isEmpty(pageDisOrder.getRecords())){
            return null;
        }
        List<OperateManagerOrderListRespDTO> respList = new ArrayList<>();
        pageDisOrder.getRecords().forEach(s -> {
            OperateManagerOrderListRespDTO respDTO = new OperateManagerOrderListRespDTO();
            respDTO.setTitle(s.getBizOrderTitle());
            respDTO.setOrderAmount(s.getOrderAmount());
            respDTO.setCommission(s.getCommission());
            respDTO.setCreateTime(DateUtil.getTimeStamp(s.getCreateTime()));
            respDTO.setMobile(s.getMobile());
            respDTO.setRealName(s.getRealName());
            respDTO.setNickName(s.getNickName());
            respList.add(respDTO);
        });
        return respList;
    }

    @Override
    public List<PartnerListRespDTO> partnerList() {
        LambdaQueryWrapper<DisPartner> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DisPartner::getPartnerStatus, ConstantUtils.Valid);
        if (!SecurityUtils.isAdmin()){
            wrapper.eq(DisPartner::getPartnerId,getUserBelongToPartnerId());
        }
        List<DisPartner> list = disPartnerPlusService.list(wrapper);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        List<PartnerListRespDTO> respList = new ArrayList<>();
        list.forEach(s -> {
            PartnerListRespDTO dto = new PartnerListRespDTO();
            dto.setPartnerId(s.getPartnerId());
            dto.setPartnerName(s.getPartnerName());
            respList.add(dto);
        });
        return respList;
    }

    @Override
    public List<PartnerUserListRespDTO> partnerUserList() {
        if (SecurityUtils.isAdmin()){
            return null;
        }
        List<PartnerUserListRespDTO> respList = new ArrayList<>();
        Long currentUserId = SecurityUtils.getCurrentUserId();
        LambdaQueryWrapper<DisPartner> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DisPartner::getPartnerStatus, ConstantUtils.Valid);
        wrapper.eq(DisPartner::getSysUserId,currentUserId);
        List<DisPartner> list = disPartnerPlusService.list(wrapper);

        if (CollectionUtils.isEmpty(list)){
            LambdaQueryWrapper<DisPartnerUser> userWrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DisPartner::getSysUserId,currentUserId);
            List<DisPartnerUser> userList = disPartnerUserPlusService.list(userWrapper);
            if (CollectionUtils.isEmpty(userList)){
                return null;
            }else {
                DisPartnerUser s = userList.get(0);
                PartnerUserListRespDTO respDTO = new PartnerUserListRespDTO();
                LambdaQueryWrapper<WxUser> wxUserWrapper = new LambdaQueryWrapper<>();
                wxUserWrapper.eq(WxUser::getOpenId,s.getOpenId());
                WxUser one = wxUserPlusService.getOne(wxUserWrapper);
                if (Objects.isNull(one)){
                    return null;
                }
                respDTO.setUserId(one.getId().longValue());
                respDTO.setOpenId(s.getOpenId());
                respDTO.setRealName(s.getRealName());
                respDTO.setNickName(s.getNickName());
                respList.add(respDTO);
                return respList;
            }
        }
        DisPartner disPartner = list.get(0);
        LambdaQueryWrapper<DisPartnerUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(DisPartnerUser::getPartnerId,disPartner.getPartnerId());
        List<DisPartnerUser> userList = disPartnerUserPlusService.list(userWrapper);
        if (CollectionUtils.isEmpty(userList)){
            return null;
        }
        userList.forEach(s -> {
            PartnerUserListRespDTO respDTO = new PartnerUserListRespDTO();
            LambdaQueryWrapper<WxUser> wxUserWrapper = new LambdaQueryWrapper<>();
            wxUserWrapper.eq(WxUser::getOpenId,s.getOpenId());
            WxUser one = wxUserPlusService.getOne(wxUserWrapper);
            if (Objects.isNull(one)){
                return;
            }
            respDTO.setUserId(one.getId().longValue());
            respDTO.setOpenId(s.getOpenId());
            respDTO.setRealName(s.getRealName());
            respDTO.setNickName(s.getNickName());
            respList.add(respDTO);
        });
        return respList;
    }

    @Override
    public LoginUserIdentityRespDTO loginUserIdentity() {
        LoginUserIdentityRespDTO respDTO = new LoginUserIdentityRespDTO();
        Long currentUserId = SecurityUtils.getCurrentUserId();
        String mobile = SecurityUtils.getCurrentUserMobile();
        respDTO.setMobile(mobile);
        respDTO.setUserId(currentUserId);
        //respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.Normal.getUserIdentity());
        respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
        if (SecurityUtils.isAdmin()){
            //respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.Admin.getUserIdentity());
            respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
            log.info("当前登录用户身份【admin】respDTO="+ JSON.toJSONString(respDTO));
            return respDTO;
        }
        //查询是否是管理员
        LambdaQueryWrapper<DisPartner> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DisPartner::getPartnerStatus, ConstantUtils.Valid);
        wrapper.eq(DisPartner::getMobile,mobile);
        List<DisPartner> list = disPartnerPlusService.list(wrapper);
        if (!CollectionUtils.isEmpty(list)){
            //respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.Manager.getUserIdentity());
            respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
            respDTO.setPartnerId(list.get(0).getPartnerId());
            log.info("当前登录用户身份【管理员】respDTO="+ JSON.toJSONString(respDTO));
            return respDTO;
        }
        LambdaQueryWrapper<DisPartnerUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(DisPartnerUser::getMobile,mobile);
        List<DisPartnerUser> userList = disPartnerUserPlusService.list(userWrapper);
        if (!CollectionUtils.isEmpty(userList)){
            //respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.SubManager.getUserIdentity());
            respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
            respDTO.setPartnerId(userList.get(0).getPartnerId());
            log.info("当前登录用户身份【子管理员】respDTO="+ JSON.toJSONString(respDTO));
            return respDTO;
        }
        LambdaQueryWrapper<DisChannel> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(DisChannel::getAdminMobile,SecurityUtils.getCurrentUserMobile());
        List<DisChannel> list1 = disChannelPlusService.list(wrapper1);
        if (!CollectionUtils.isEmpty(list1)){
            respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
            respDTO.setChannelCode(list1.get(0).getChannelCode());
            log.info("当前登录用户身份【渠道管理员】respDTO="+ JSON.toJSONString(respDTO));
            return respDTO;
        }
        LambdaQueryWrapper<DisChannelMember> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(DisChannelMember::getMemberMobile,SecurityUtils.getCurrentUserMobile());
        List<DisChannelMember> list2 = memberPlusService.list(wrapper2);
        if (!CollectionUtils.isEmpty(list2)){
            respDTO.setUserIdentity(LoginUserIdentityRespDTO.UserIdentityEnum.ChannelManager.getUserIdentity());
            respDTO.setChannelCode(list2.get(0).getChannelCode());
            log.info("当前登录用户身份【渠道管理成员】respDTO="+ JSON.toJSONString(respDTO));
            return respDTO;
        }
        log.info("当前登录用户身份【普通用户】respDTO="+ JSON.toJSONString(respDTO));
        return respDTO;
    }

    @Override
    public List<WxUserDto.UserChain> superiorChain(String openId) {
        List<WxUserDto.UserChain> list = new ArrayList<>();

        //查询上级
        LambdaQueryWrapper<WxUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WxUser::getOpenId,openId);
        WxUser one = wxUserPlusService.getOne(wrapper);

        if (StringUtils.isNotBlank(one.getSuperior())){
            LambdaQueryWrapper<WxUser> preWrapper = new LambdaQueryWrapper<>();
            preWrapper.eq(WxUser::getOpenId,one.getSuperior());
            WxUser wxUser = wxUserPlusService.getOne(preWrapper);
            WxUserDto.UserChain preChain = new WxUserDto.UserChain();
            preChain.setLevel(0);
            preChain.setRealName(wxUser.getRealName());
            preChain.setMobile(wxUser.getMobile());
            preChain.setOpenId(wxUser.getOpenId());
            preChain.setNickName(wxUser.getNickname());
            list.add(preChain);
        }
        //查询下级
        List<WxUserDto.UserChain> nextChainList = assembileNextChain(openId);
        if (CollectionUtils.isEmpty(nextChainList)){
            return list;
        }
        nextChainList = nextChainList.parallelStream().filter(Objects::nonNull).collect(Collectors.toList());
        list.addAll(nextChainList);
        return list;
    }

    private List<WxUserDto.UserChain> assembileNextChain(String openId){
        List<WxUserDto.UserChain> list = new ArrayList<>();
        LambdaQueryWrapper<WxUser> nextWrapper = new LambdaQueryWrapper<>();
        nextWrapper.eq(WxUser::getSuperior,openId);
        List<WxUser> nextList = wxUserPlusService.list(nextWrapper);
        final int[] level = {1};
        if (!CollectionUtils.isEmpty(nextList)){
            List<String> openIdList = nextList.stream().map(WxUser::getOpenId).collect(Collectors.toList());
            LambdaQueryWrapper<WxUser> nextUserWrapper = new LambdaQueryWrapper<>();
            nextUserWrapper.in(WxUser::getSuperior,openIdList);
            List<WxUser> nextUserList = wxUserPlusService.list(nextUserWrapper);
            nextUserList.forEach(s -> {
                WxUserDto.UserChain nextChain = new WxUserDto.UserChain();
                nextChain.setLevel(level[0]);
                nextChain.setRealName(s.getRealName());
                nextChain.setMobile(s.getMobile());
                nextChain.setOpenId(s.getOpenId());
                nextChain.setNickName(s.getNickname());
                list.add(nextChain);
                level[0]++;
                assembileNextChain(s.getOpenId());
            });
        }
        return list;
    }

    private Long getUserBelongToPartnerId(){
        Long currentUserId = SecurityUtils.getCurrentUserId();
        LambdaQueryWrapper<DisPartner> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DisPartner::getPartnerStatus, ConstantUtils.Valid);
        wrapper.eq(DisPartner::getSysUserId,currentUserId);
        List<DisPartner> list = disPartnerPlusService.list(wrapper);
        if (!CollectionUtils.isEmpty(list)){
            log.info("查询用户归属合伙人="+JSON.toJSONString(list.get(0)));
            return list.get(0).getPartnerId();
        }

        LambdaQueryWrapper<DisPartnerUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(DisPartnerUser::getSysUserId,currentUserId);
        List<DisPartnerUser> userList = disPartnerUserPlusService.list(userWrapper);
        if (!CollectionUtils.isEmpty(userList)){
            log.info("查询用户归属合伙人="+JSON.toJSONString(userList.get(0)));
            return userList.get(0).getPartnerId();
        }
        log.info("查询用户归属合伙人=-1");
        return -1L;
    }

    private List<DisPartnerUser> getPartnerUserList(Long partnerId){

        LambdaQueryWrapper<DisPartnerUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(DisPartnerUser::getPartnerId,partnerId);
        List<DisPartnerUser> userList = disPartnerUserPlusService.list(userWrapper);
        if (CollectionUtils.isEmpty(userList)){
            return null;
        }
        return userList;
    }
}
